#include "convert.h"


alp_status_t convert_node(bencode_node_t * node, const char* fromcode)
{
	switch(node->type )
	{
	case BENCODE_INT:
		break;	//do nothing
	case BENCODE_STRING:
		ALP_CHECK(convert_string(node, fromcode));
		break;
	case BENCODE_LIST:
		ALP_CHECK(convert_list(node->list,fromcode));
		break;
	case BENCODE_DICT:
		ALP_CHECK(convert_dict(node->dict,fromcode));
		break;
	default:
		return ALP_E_INPUT;
	}
	return 0; //success
}

alp_status_t convert_string(bencode_node_t* node, const char* fromcode)
{
	const char* temp;
	char* dstbuffer;		//the destination
	size_t * outlen;
	alp_iconv_t * ic;
	const char* tocode = "utf-8";

	dstbuffer = (char*) malloc(2*node->length);
	outlen = (size_t*)malloc(sizeof(size_t));
	*outlen = 2*node->length;

	
	alp_iconv_create(&ic, fromcode, tocode);
	if(alp_iconv(ic, node->buffer, &node->length, dstbuffer, outlen))
	{
		printf("Some error occured when convert\n");
		return -1;
	}
	//convert successfully
	temp = node->buffer;
	node->buffer = dstbuffer;
	node->length = *outlen;
	free(temp);		//free old buffer
	alp_iconv_destroy(ic);	//destroy ic
	return 0;
}

alp_status_t convert_list(alp_list_t* list, const char* fromcode)
{
	alp_list_index_t * li = list->first;
	while(li!=0)
	{
		ALP_CHECK(convert_node((bencode_node_t*)li->data,fromcode));
		li = li->next;
	}
	return 0;
}

alp_status_t convert_dict(alp_dict_t* dict, const char* fromcode)
{
	size_t i;
	for(i=0; i<dict->count; ++i)
	{
		char *p, *newfromcode;
		size_t codelen;
		alp_list_index_t * li = dict->buckets[i]->first;
		while(li!=0)
		{
			p = (char*)memchr(((entry_t*)li->data)->key, '.', ((entry_t*)li->data)->klen);
			if(p)		//new fromcode type
			{
				codelen = ((char*)((entry_t*)li->data)->key) + ((entry_t*)li->data)->klen - p;
				newfromcode = (char*) malloc(codelen+1);	//1 for buffer
				memcpy(newfromcode,p+1,codelen);
				newfromcode[codelen]='\0';
				if(!isUTF8(newfromcode))
					ALP_CHECK(convert_node((bencode_node_t*)(((entry_t*)li->data)->val), newfromcode));
				free(newfromcode);
			}
			else if(!isUTF8(fromcode))	//fromcode isn't utf-8
				ALP_CHECK(convert_node((bencode_node_t*)(((entry_t*)li->data)->val),fromcode));	//then convert
			li = li->next;
		}
	}
	return 0;
}

alp_status_t convert(bencode_node_t* node)
{
	char* fromcode;
	bencode_node_t* t = (bencode_node_t*)alp_dict_get(node->dict, "encoding", 8);
	if(t)
	{
		if(t->type != BENCODE_STRING)
		{
			printf("cannot get the fromcode\n");
			return -1;
		}
		fromcode = (char*)malloc(t->length+1);
		memcpy(fromcode,t->buffer,t->length);
		fromcode[t->length] = '\0';
	}
	else
	{
		fromcode = (char*) malloc(6);
		fromcode = "utf-8";
	}
	if(convert_node(node,fromcode))
	{
		free(fromcode);
		return -1;
	}
	free(fromcode);
	return 0;
}

alp_status_t isUTF8(const char* c)
{
	const char* u = "utf-8";
	if(memcmp(u,c,5))
		return 0;
	return 1;
}



